/*
树链剖分：树中任意一条路径->O(logn)段连续区间
分析：减少计算量，降低复杂度(重儿子的结果可以重复利用)

*/
#pragma GCC optimize("O1,O2,O3,Ofast")
#pragma GCC optimize("no-stack-protector,unroll-loops,fast-math,inline")
#pragma GCC target("avx,avx2,fma")
#pragma GCC target("sse,sse2,sse3,sse4,sse4.1,sse4.2,ssse3")

#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
using namespace std;
#define DEBUG

inline int read()
{
    int c=getchar(), f=1, x=0;
    if(c=='-') f*=-1, x=getchar();
    while(c<'0'&&'9'<c) c=getchar();
    while('0'<=c&&c<='9') 
        x=(x<<3)+(x<<1)+c-'0', c=getchar();
    return f*x;
}
inline void write(long long x)
{
    if(x>=10) write(x/10);
    putchar(x%10+'0');
}
using ll=long long;
using PII=pair<int, int>;
#define x first
#define y second
#define DEBUG
const int N=3e5+10, INF=0x3f3f3f3f;
int n, m;
struct node
{
    int sz, fa, heaveson; //以当前为根节点的字数大小 父节点 重孩子
    vector<int> sons;
} tree[N];
ll ans[N];
int a[N];
//各个mp存储映射 <a[i], <与a[i]的最小差值,a[i].cnt>>
void init()
{
    n=read();
    for(int i=2; i<=n; i++)
    {
        tree[i].fa=read();
        tree[tree[i].fa].sons.emplace_back(i);
    }

    for(int i=1; i<=n; i++)
        a[i]=read();
}

void update(int u) //更新子树大小和权值
{
    tree[u].sz=1;
    for(int v:tree[u].sons)
    {
        update(v);
        tree[u].sz+=tree[v].sz;
        if (!tree[u].heaveson || tree[v].sz>tree[tree[u].heaveson].sz) tree[u].heaveson= v;
    }
}
//插入<val, <最小差值,valcnt>>到mp中，并更新节点u的权值
void update(int u, int val, int cnt, map<int, PII>& mp)
{
    //val已经存在于mp中
    if(mp.count(val))
    {
        auto &cur=mp[val];
        ans[u]-=1ll*cur.x*cur.x*cur.y; //删掉旧的计算结果
        cur.x=0, cur.y+=cnt; //最小差值可能更改 计算新的cnt
        return;
    }

    //执行插入
    mp[val]={INF*(cnt==1), cnt}; //初始化
    auto& cur=mp[val];
    //分别考虑最接近val的前一个元素和后一个元素的影响(可能更新权值)
    //处理val前一个值的情况
    auto it=mp.lower_bound(val); //找到大于等于val的第一个值
    if(it!=mp.begin()) //存在
    {
        --it; //转为小于
        auto &pre=it->y; //mp[小于val的max]
        cur.x=min(cur.x, val-it->x); //取两个差值的最小值
        if(pre.y)
        {
            ans[u]-=1ll*pre.x*pre.x*pre.y; //去掉旧元素贡献
            pre.x=min(pre.x, val-it->x);
            ans[u]+=1ll*pre.x*pre.x*pre.y; //加上新元素贡献
        }
    }

    it=mp.upper_bound(val); //找到第一个大于val的第一个值
    if(it!=mp.end()) //存在
    {
        auto &suf=it->y; //mp[小于val的max]
        cur.x=min(cur.x, it->x-val); //取两个差值的最小值
        if(suf.y)
        {
            ans[u]-=1ll*suf.x*suf.x*suf.y; //去掉旧元素贡献
            suf.x=min(suf.x, it->x-val);
            ans[u]+=1ll*suf.x*suf.x*suf.y; //加上新元素贡献
        }
    }
    ans[u]+=1ll*cur.x*cur.x*cur.y; //加上更新后的val
}

void dfs(int u, map<int, PII>& mp) //mp以节点u为根的子树的映射
{
    if(tree[u].sons.empty()) //处理叶子节点
    {
        mp[a[u]]={INF, 1};
        ans[u]=1ll*INF*INF; //保证叶子节点对其他平方差无效
        return;
    }
    dfs(tree[u].heaveson, mp); //优先处理重孩子

    ans[u]=ans[tree[u].heaveson];
    update(u, a[u], 1, mp); //添加当前节点权值
    for(auto v:tree[u].sons)
    {
        if(v==tree[u].heaveson) continue; //重儿子已经更新
        map<int, PII> temp; //每一个轻儿子子树存储一套轻儿子映射，避免轻儿子之间干扰
        dfs(v, temp);
        for(auto it:temp)
            update(u, it.x, it.y.y, mp); //把当前子树的权值加入到父节点传入的映射组，并更新u的答案
    }

}

void solve()
{
    init();
    update(1);
    map<int, PII> mp;
    dfs(1, mp);
    for(int i=1; i<=n; i++) 
        write(ans[i]!=1ll*INF*INF?ans[i]:0), puts("");
}

signed main()
{
    #ifdef DEBUG
        freopen("../in.txt", "r", stdin);
        freopen("../out.txt", "w", stdout);
    #endif

    int T=1; //cin >> T; 
    while(T--) 
    {
        solve();
    }
    return 0;
}